package com.java.netty.nio.netty.codec;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;

import java.util.concurrent.TimeUnit;


/**
 * @Author: Dgg
 * @Date: 2021/12/11 22:20
 * 1.我们自定义个handler 需要继承netty 规定的好的某个handler适配器
 * 2.这时候我们自定义的handler 才能称之为handler
 */
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
	//读取数据时间（这里可以读取客户端你发送的消息）

	/**
	 * @param ctx channelHandler  ctx:上下文对象 ，含有管道pipeline ，通道channel ，地址
	 * @param msg 客户端发送的数据 ，默认object 类型
	 * @throws Exception
	 */
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//		System.out.println("服务端读取线程：" + Thread.currentThread().getName());
//		System.out.println("server ctx:" + ctx);
//		System.out.println("看看channel和pipline的关系");
//		Channel channel = ctx.channel();
//		ChannelPipeline pipeline = ctx.pipeline();//本质是一个双向链表,涉及到出栈入栈问题
//		//将我们的msg 转换成byteBuffer
//		//ByteBuf 是Netty 提供，不是NIO的 ByteBuffer
//		ByteBuf buffer = (ByteBuf) msg;
//		System.out.println("Sent by the Client:" + ((ByteBuf) msg).toString(CharsetUtil.UTF_8));
//		System.out.println("Cilet IP:" + ctx.channel().remoteAddress());

		//举例子我们有一个非常耗时的业务 -> 异步执行 -> 提交该channel 对应的taskQueue

		//举例子用户自定义
//		ctx.channel().eventLoop().execute(new Runnable() {
//			@Override
//			public void run() {
//				try {
//					Thread.sleep(10 * 1000);
//					ctx.writeAndFlush(Unpooled.copiedBuffer("Hello client,狗叫~2", CharsetUtil.UTF_8));
//				} catch (InterruptedException e) {
//					e.printStackTrace();
//				}
//			}
//		});
		//提交到scheduleTaskQueue
		ctx.channel().eventLoop().schedule((Runnable) () -> {
			try {
				Thread.sleep(5 * 1000);
				ctx.writeAndFlush(Unpooled.copiedBuffer("Hello client,狗叫~4 ", CharsetUtil.UTF_8));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}, 5, TimeUnit.SECONDS);
	}

	//读取数据完毕
	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		//writeAndFlush 他是write 加上flush ，作用是把数据写入到缓存并刷新
		//一般来讲，我们对发送的数据 进行一个编码
		System.out.println("服务端读取数据完毕发送消息");
		ctx.writeAndFlush(Unpooled.copiedBuffer("Hello client,狗叫~", CharsetUtil.UTF_8));
	}

	//处理异常方法,一般是需要关闭通道

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		ctx.close();
	}
}
